home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cpp_libs / vector.lha / vector / hmatrix.h < prev    next >
C/C++ Source or Header  |  1991-11-23  |  9KB  |  288 lines

  1. #ifndef _HMATRIX_H
  2. #define _HMATRIX_H
  3.  
  4. #include "cmatrix.h"
  5. #include "hvector.h"
  6.  
  7. #define HomogenousMatrixDeclare(T) \
  8. class HMat(T) {                        \
  9. protected:                        \
  10.     T    m[4][4];                    \
  11.                             \
  12. public:                            \
  13.     enum { columns, rows };                \
  14.                             \
  15.     HMat(T)() {}                    \
  16.     HMat(T)(int flag,                    \
  17.         const HVec(T) &x,                \
  18.         const HVec(T) &y,                \
  19.         const HVec(T) &z,                \
  20.         const HVec(T) &w);                \
  21.                             \
  22.     const T *operator()(int i) const {            \
  23.     return m[i];                    \
  24.     }                            \
  25.     T *operator[](int i) { return m[i]; }        \
  26.     HMat(T) &zero();                    \
  27.     HMat(T) &identity();                \
  28.                             \
  29.     HMat(T) transpose() const;                \
  30.                             \
  31.     /* Dehomogenize a matrix */                \
  32.        operator CMat(T)() const;            \
  33.                             \
  34.     /* Homogenize a matrix */                \
  35.     HMat(T)(const CMat(T) &v);                \
  36. };                            \
  37.                             \
  38. HVec(T) operator*(const HMat(T) &m, const HVec(T) &v);    \
  39. HVec(T) operator*(const HVec(T) &v, const HMat(T) &m);    \
  40. HMat(T) operator*(const HMat(T) &a, const HMat(T) &b);    \
  41. /* These are for transformation matrices */        \
  42. inline HMat(T) operator*(                \
  43.     const HMat(T) &a,                    \
  44.     const CMat(T) &b)                    \
  45. {                            \
  46.     return a * HMat(T)(b);                \
  47. }                            \
  48. inline HMat(T) operator*(                \
  49.     const CMat(T) &a,                    \
  50.     const HMat(T) &b)                    \
  51. {                            \
  52.     return HMat(T)(a) * b;                \
  53. }                            \
  54.                             \
  55. /* Only implemented for HMat(float) */            \
  56. HMat(T) adjoint(const HMat(T) &m, T *det = NULL);   \
  57.                             \
  58. HMat(T) view_matrix(                    \
  59.     const HVec(T) &eye,                    \
  60.     const HVec(T) &lookat,                \
  61.     const HVec(T) &vup);                \
  62. HMat(T) perspective_matrix(T fov, T znear, T zfar); \
  63. HMat(T) screen_matrix(T size, T offset);        \
  64.                             \
  65. ostream &operator<<(ostream &o, const HMat(T) &m);
  66.  
  67. #define HomogenousMatrixImplement(T) \
  68.                             \
  69. static const int                    \
  70.     X = 0,                        \
  71.     Y = 1,                        \
  72.     Z = 2,                        \
  73.     W = 3;                        \
  74.                             \
  75. /* Initialize a matrix by either columns or rows */    \
  76. HMat(T)::HMat(T)(                    \
  77.     int flag,                        \
  78.     const HVec(T) &x,                    \
  79.     const HVec(T) &y,                    \
  80.     const HVec(T) &z,                    \
  81.     const HVec(T) &w)                    \
  82. {                            \
  83.     for (int i = X; i <= W; i++) {            \
  84.     if (flag == HMat(T)::columns) {            \
  85.         m[i][X] = x(i);                \
  86.         m[i][Y] = y(i);                \
  87.         m[i][Z] = z(i);                \
  88.         m[i][W] = w(i);                \
  89.     } else if (flag == HMat(T)::rows) {        \
  90.         m[X][i] = x(i);                \
  91.         m[Y][i] = y(i);                \
  92.         m[Z][i] = z(i);                \
  93.         m[W][i] = w(i);                \
  94.     } else {                    \
  95.         cerr << "HMat(T)::HMat(T): bad flag "    \
  96.          << "(not rows or columns)" << endl;    \
  97.         zero();                    \
  98.     }                        \
  99.     }                            \
  100. }                            \
  101.                             \
  102. HMat(T) &HMat(T)::zero() {                \
  103.     for (int i = X; i <= W ; i++)            \
  104.     for (int j = X; j <= W; j++)            \
  105.         m[i][j] = 0;                \
  106.     return *this;                    \
  107. }                            \
  108.                             \
  109. HMat(T) &HMat(T)::identity() {                \
  110.     for (int i = X; i <= W ; i++)            \
  111.     for (int j = X; j <= W; j++)            \
  112.         m[i][j] = (i == j);                \
  113.     return *this;                    \
  114. }                            \
  115.                             \
  116. /* Return the transpose of a matrix */            \
  117. HMat(T) HMat(T)::transpose() const {            \
  118.     HMat(T) tran;                    \
  119.                             \
  120.     for (int i = X; i <= W; i++)            \
  121.     for (int j = X; j <= W; j++)            \
  122.         tran[i][j] = m[j][i];            \
  123.                             \
  124.     return tran;                    \
  125. }                            \
  126.                             \
  127. /* Dehomogenize a matrix */                \
  128. HMat(T)::operator CMat(T)() const {            \
  129.     CMat(T) res;                    \
  130.                             \
  131.     for (int i = X; i <= Z; i++)            \
  132.     for (int j = X; j <= W; j++)            \
  133.         res[i][j] = m[i][j];            \
  134.                             \
  135.     return res;                        \
  136. }                            \
  137.                             \
  138. HMat(T)::HMat(T)(const CMat(T) &v) {            \
  139.     for (int i = X; i <= Z; i++)            \
  140.     for (int j = X; j <= W; j++)            \
  141.         m[i][j] = v(i)[j];                \
  142.                             \
  143.     /* No perspective component */            \
  144.     m[W][X] = m[W][Y] = m[W][Z] = 0;            \
  145.     m[W][W] = 1;                    \
  146. }                            \
  147.                             \
  148. /* M = M * V */                            \
  149. HVec(T) operator*(const HMat(T) &m, const HVec(T) &v) {        \
  150.     return HVec(T)(                        \
  151.     m(X)[X]*v(X)+m(X)[Y]*v(Y)+m(X)[Z]*v(Z)+m(X)[W]*v(W),    \
  152.     m(Y)[X]*v(X)+m(Y)[Y]*v(Y)+m(Y)[Z]*v(Z)+m(Y)[W]*v(W),    \
  153.     m(Z)[X]*v(X)+m(Z)[Y]*v(Y)+m(Z)[Z]*v(Z)+m(Z)[W]*v(W),    \
  154.     m(W)[X]*v(X)+m(W)[Y]*v(Y)+m(W)[Z]*v(Z)+m(W)[W]*v(W));    \
  155. }                                \
  156.                                 \
  157. /* M = V * M */                            \
  158. HVec(T) operator*(const HVec(T) &v, const HMat(T) &m) {        \
  159.     return HVec(T)(                        \
  160.     m(X)[X]*v(X)+m(Y)[X]*v(Y)+m(Z)[X]*v(Z)+m(W)[X]*v(W),    \
  161.     m(X)[Y]*v(X)+m(Y)[Y]*v(Y)+m(Z)[Y]*v(Z)+m(W)[Y]*v(W),    \
  162.     m(X)[Z]*v(X)+m(Y)[Z]*v(Y)+m(Z)[Z]*v(Z)+m(W)[Z]*v(W),    \
  163.     m(X)[W]*v(X)+m(Y)[W]*v(Y)+m(Z)[W]*v(Z)+m(W)[W]*v(W));    \
  164. }                                \
  165.                                 \
  166. /* M = M * M */                            \
  167. HMat(T) operator*(const HMat(T) &a, const HMat(T) &b) {        \
  168.     HMat(T) res;                    \
  169.                             \
  170.     for (int i = X; i <= W; i++) {            \
  171.     for (int j = X; j <= W; j++) {            \
  172.         res[i][j] = 0;                \
  173.         for (int k = X; k <= W; k++)        \
  174.         res[i][j] += a(i)[k] * b(k)[j];     \
  175.     }                        \
  176.     }                            \
  177.                             \
  178.     return res;                        \
  179. }                            \
  180.                             \
  181. /* Construct a viewing matrix which effects a translation        \
  182.  *  of the eye to the origin, the lookat - eye vector to        \
  183.  *  the -Z axis, and the vup vector to the +Y axis.            \
  184.  * This is drawn from PPHIGS but done in RHS.                \
  185.  */                                    \
  186. HMat(T) view_matrix(                            \
  187.     const HVec(T) &eye,                            \
  188.     const HVec(T) &lookat,                        \
  189.     const HVec(T) &vup)                            \
  190. {                                    \
  191.     static HVec(T) zero(0,0,0,1);                    \
  192.     HVec(T) w = eye - lookat;     /* Look vector */            \
  193.                                     \
  194.     /* Translate eye to origin */                    \
  195.     HMat(T) trans;                            \
  196.     trans.identity();                            \
  197.     trans = trans * translation_matrix(-eye);                \
  198.                                     \
  199.     /* Construct an orthogonal basis whose up                \
  200.      *    vector v is as close to vup as possible                \
  201.      */                                    \
  202.     HVec(T) u = vup ^ w;                        \
  203.     HVec(T) v = w ^ u;                            \
  204.                                     \
  205.     u.normalize(); u[W] = 0;                        \
  206.     v.normalize(); v[W] = 0;                        \
  207.     w.normalize(); w[W] = 0;                        \
  208.                                     \
  209.     HMat(T) frame(HMat(T)::rows, u, v, w, zero);            \
  210.                                     \
  211.     return frame * trans;                        \
  212. }                                    \
  213.                                     \
  214. /* Construct a Blinn-style perspective matrix, with specified        \
  215.  *  near and far clipping planes and field of view (in degrees):    \
  216.  *                                    \
  217.  *  |    cos theta   0        0        0        |   \
  218.  *  |                                |   \
  219.  *  |                                |   \
  220.  *  |    0        cos theta    0        0        |   \
  221.  *  |                                |   \
  222.  *  |                sin theta Zf    sin theta Zf Zn |   \
  223.  *  |    0        0        ------------    --------------- |   \
  224.  *  |                  Zf - Zn        Zf - Zn    |   \
  225.  *  |                                |   \
  226.  *  |    0        0        sin theta    0        |   \
  227.  *                                    \
  228.  * This transforms into the canonical [-1..1]^2 window. Z        \
  229.  *  *decreases* with increasing depth in world space, and        \
  230.  *  *increases* with increasing depth in screen space            \
  231.  *  x' = tan theta x/-z                            \
  232.  *  y' = tan theta y/-z                            \
  233.  *        Zf          Zn                        \
  234.  *  z' = ------- (1 + --) -> z'(-Zn) = 0, z'(-Zf) = 1            \
  235.  *     Zf - Zn       z                        \
  236.  */                                    \
  237. HMat(T) perspective_matrix(float fov, float Zn, float Zf) {        \
  238.     fov = dtor(fov);                            \
  239.                                     \
  240.     float ct = cos(fov/2), st = sin(fov/2),                \
  241.       zs = st * Zf / (Zf - Zn);                    \
  242.     HMat(T) p;                                \
  243.                                     \
  244.     p.zero();                                \
  245.     /* Note that the third column is all negated so Z            \
  246.      *    increases away from the eye (in RHS, we look            \
  247.      *    down -Z instead of +Z).                        \
  248.      */                                    \
  249.     p[X][X] = ct;                            \
  250.     p[Y][Y] = ct;                            \
  251.         p[Z][Z] =-zs;   p[Z][W] =-zs * Zn;                \
  252.         p[W][Z] =-st;                        \
  253.                                     \
  254.     return p;                                \
  255. }                                    \
  256.                                     \
  257. /* Construct a matrix that transforms from the canonical        \
  258.  *  [-1..1]^2 window to a window of specified size and offset.        \
  259.  */                                    \
  260. HMat(T) screen_matrix(float size, float offset) {            \
  261.     HMat(T) p;                                \
  262.                                     \
  263.     p.zero();                                \
  264.     p[X][X] = size/2;        p[X][W] = offset;                \
  265.     p[Y][Y] = size/2;   p[Y][W] = offset;                \
  266.         p[Z][Z] = 1;                        \
  267.                 p[W][W] = 1;                \
  268.                                     \
  269.     return p;                                \
  270. }                                    \
  271.                                     \
  272. ostream &operator<<(ostream &o, const HMat(T) &m) { \
  273.     for (int i = X; i <= W; i++)            \
  274.     o << '\t' << "( "                \
  275.       << setw(8) << m(i)[X] << ' '            \
  276.       << setw(8) << m(i)[Y] << ' '            \
  277.       << setw(8) << m(i)[Z] << ' '            \
  278.       << setw(8) << m(i)[W] << " )\n";        \
  279.                             \
  280.     return o;                        \
  281. }
  282.  
  283. HomogenousMatrixDeclare(float);
  284.  
  285. typedef HMat(float) HMatrix;
  286.  
  287. #endif /*_HMATRIX_H*/
  288.